from rest_framework import serializers
from apps.goods.models import SKU, SKUSpecification, SPUSpecification, SpecificationOption
from django.db import transaction

class SKUSpecificationSerialzier(serializers.ModelSerializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        model = SKUSpecification
        fields = ('spec_id', 'option_id')


class SKUSerializer(serializers.ModelSerializer):
    """
     {
                "spu": "商品SPU名称",
                "spu_id": "商品SPU ID",
                "category_id": "三级分类id",
                "category": "三级分类名称",
                "specs": [
                    {
                        "spec_id": "规格id",
                        "option_id": "选项id"
                    },
    """
    # 关联外键返回  sku表关联spu表和分类表  副表嵌套主表返回
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()
    category = serializers.StringRelatedField(read_only=True)
    category_id = serializers.IntegerField()

    # sku具体规格表关联sku表  sku表嵌套sku具体规格表返回 主表嵌套副表返回
    # 一个sku商品对应多个规格选项
    specs = SKUSpecificationSerialzier(many=True)

    class Meta:
        model = SKU
        fields = '__all__'

    def create(self, validated_data):
        """
            保存sku表的同时需要保存sku具体规格表
        :param validated_data:
        :return:
        """
        # 取出规格数据
        # specs = validated_data['specs']
        # # 删除规格数据方便保存sku表
        # del validated_data['specs']
        with transaction.atomic():
            # 事务使用 1、设置保存点，在出现错误时回滚到保存点
            save_point = transaction.savepoint()
            try:
                specs = validated_data.pop('specs')
                # 保存sku表
                sku = SKU.objects.create(**validated_data)

                # 保存sku具体规格表
                for spec_option in specs:
                    SKUSpecification.objects.create(sku=sku, option_id=spec_option['option_id'], spec_id=spec_option['spec_id'])
            except:
                # 捕获到异常，说明有代码出现问题需要回滚到保存点
                transaction.savepoint_rollback(save_point)
                # 没有捕获到异常 提交
            transaction.savepoint_commit(save_point)
        return sku

    def update(self, instance, validated_data):
        """
            更新sku表 ，更新sku具体规格表
        :param instance:  sku表对象
        :param validated_data:
        :return:
        """
        with transaction.atomic():
            # 事务使用 1、设置保存点，在出现错误时回滚到保存点
            save_point = transaction.savepoint()
            try:
                specs = validated_data.pop('specs')
                # 更新sku表
                SKU.objects.filter(id=instance.id).update(**validated_data)
                sku = SKU.objects.get(id=instance.id)
                # 更新sku具体规格表
                for spec_option in specs:
                    SKUSpecification.objects.filter(sku=sku, spec_id=spec_option['spec_id']).update(
                        option_id=spec_option['option_id'])
            except:
                # 捕获到异常，说明有代码出现问题需要回滚到保存点
                transaction.savepoint_rollback(save_point)
                # 没有捕获到异常 提交
            transaction.savepoint_commit(save_point)

        return sku


class SpecificationOptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = ('id', 'value')


class SPUSpecificationSerializer(serializers.ModelSerializer):
    """
     {
            "id": "规格id",
            "name": "规格名称",
            "spu": "SPU商品名称",
            "spu_id": "SPU商品id",
            "options": [
                {
                    "id": "选项id",
                    "name": "选项名称"
                },
                ...
            ]
        },
    """
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()

    options = SpecificationOptionSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = '__all__'
